import sys
import json
import threading
from datetime import datetime
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                               QHBoxLayout, QLineEdit, QPushButton, QListWidget, QListWidgetItem,
                               QTextEdit, QLabel, QStackedWidget, QFormLayout,
                               QMessageBox, QSplitter, QFrame, QTabWidget)
from PySide6.QtCore import Qt, Signal, QObject, QThread, QUrl
from PySide6.QtGui import QFont, QColor, QPalette, QIcon, QTextCursor, QKeySequence, QShortcut
import socketio
import time
import malword
# 全局样式表 - 红色系主题
RED_THEME_STYLESHEET = """
QMainWindow, QWidget {
    background-color: #f8f0f0;
}

QLabel {
    color: #333333;
    font-size: 14px;
}

QLabel#titleLabel {
    color: #d32f2f;
    font-size: 24px;
    font-weight: bold;
}

QLineEdit, QTextEdit {
    border: 1px solid #e57373;
    border-radius: 4px;
    padding: 6px 10px;
    background-color: #ffffff;
    color: #333333;
    font-size: 14px;
}

QLineEdit:focus, QTextEdit:focus {
    border-color: #d32f2f;
    outline: none;
}

QPushButton {
    background-color: #d32f2f;
    color: white;
    border: none;
    border-radius: 4px;
    padding: 8px 16px;
    font-size: 14px;
    font-weight: 500;
}

QPushButton:hover {
    background-color: #c62828;
}

QPushButton:pressed {
    background-color: #b71c1c;
}

QPushButton:disabled {
    background-color: #e57373;
    color: #f5f5f5;
}

QListWidget {
    border: 1px solid #e57373;
    border-radius: 4px;
    background-color: #ffffff;
}

QListWidget::item {
    padding: 6px 10px;
    border-bottom: 1px solid #f0f0f0;
}

QListWidget::item:hover {
    background-color: #ffebee;
}

QListWidget::item:selected {
    background-color: #ef5350;
    color: white;
}

QTabWidget::pane {
    border: 1px solid #e57373;
    border-radius: 4px;
    background-color: #ffffff;
}

QTabBar::tab {
    background-color: #fce4ec;
    color: #d32f2f;
    padding: 8px 16px;
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    margin-right: 2px;
}

QTabBar::tab:selected {
    background-color: #ffffff;
    border: 1px solid #e57373;
    border-bottom-color: #ffffff;
}

QSplitter::handle {
    background-color: #e57373;
}

QSplitter::handle:horizontal {
    width: 2px;
}

QSplitter::handle:vertical {
    height: 2px;
}

QFrame#chatFrame {
    border: 1px solid #e57373;
    border-radius: 4px;
    background-color: #ffffff;
}

QLabel#messageSender {
    color: #d32f2f;
    font-weight: bold;
}

QLabel#messageTime {
    color: #9e9e9e;
    font-size: 12px;
}

QLabel#onlineUserLabel {
    background-color: #d32f2f;
    color: white;
    padding: 6px 10px;
    font-weight: bold;
}
"""

# WebSocket客户端线程
class SocketIOClientThread(QThread):
    # 信号定义
    user_online = Signal(dict)
    user_offline = Signal(dict)
    online_users = Signal(list)
    public_message_received = Signal(dict)
    private_message_received = Signal(dict)
    connection_error = Signal(str)
    
    def __init__(self, user_id, username):
        super().__init__()
        self.user_id = user_id
        self.username = username
        self.sio = socketio.Client(reconnection=True)
        self.connected = False
        
        # 注册事件处理函数
        self.sio.on('connect', self.on_connect)
        self.sio.on('disconnect', self.on_disconnect)
        self.sio.on('user_online', self.on_user_online)
        self.sio.on('user_offline', self.on_user_offline)
        self.sio.on('online_users', self.on_online_users)
        self.sio.on('public_message', self.on_public_message)
        self.sio.on('private_message', self.on_private_message)
        self.sio.on('connect_error', self.on_connect_error)
    
    def run(self):
        try:
            self.sio.connect('http://localhost:5000')
            self.sio.wait()
        except Exception as e:
            self.connection_error.emit(f"连接错误: {str(e)}")
    
    def on_connect(self):
        self.connected = True
        print("WebSocket连接成功")
        # 发送登录信息
        self.sio.emit('login', {'user_id': self.user_id, 'username': self.username})
    
    def on_disconnect(self):
        self.connected = False
        print("WebSocket连接断开")
    
    def on_connect_error(self, data):
        self.connection_error.emit(f"连接失败: {str(data)}")
    
    def on_user_online(self, data):
        self.user_online.emit(data)
    
    def on_user_offline(self, data):
        self.user_offline.emit(data)
    
    def on_online_users(self, data):
        self.online_users.emit(data)
    
    def on_public_message(self, data):
        self.public_message_received.emit(data)
    
    def on_private_message(self, data):
        self.private_message_received.emit(data)
    
    def send_public_message(self, content):
        if self.connected:
            self.sio.emit('public_message', {
                'sender_id': self.user_id,
                'content': malword.rplace(content)
            })
    
    def send_private_message(self, receiver_id, content):
        if self.connected:
            self.sio.emit('private_message', {
                'sender_id': self.user_id,
                'receiver_id': receiver_id,
                'content': malword.rplace(content)
            })

# 登录窗口
class LoginWindow(QWidget):
    login_success = Signal(int, str)  # user_id, username
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.init_ui()
        
    def init_ui(self):
        self.setWindowTitle("烈火聊天室 - 登录")
        self.setFixedSize(400, 300)
        
        layout = QVBoxLayout()
        layout.setContentsMargins(50, 30, 50, 30)
        layout.setSpacing(15)
        
        # 标题
        title_label = QLabel("烈火聊天室")
        title_label.setObjectName("titleLabel")
        title_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(title_label)
        
        # 表单布局
        form_layout = QFormLayout()
        form_layout.setSpacing(10)
        
        self.username_edit = QLineEdit()
        self.username_edit.setPlaceholderText("请输入用户名")
        form_layout.addRow("用户名:", self.username_edit)
        
        self.password_edit = QLineEdit()
        self.password_edit.setEchoMode(QLineEdit.Password)
        self.password_edit.setPlaceholderText("请输入密码")
        form_layout.addRow("密码:", self.password_edit)
        
        layout.addLayout(form_layout)
        
        # 按钮布局
        button_layout = QHBoxLayout()
        button_layout.setSpacing(10)
        
        self.login_button = QPushButton("登录")
        self.login_button.clicked.connect(self.handle_login)
        button_layout.addWidget(self.login_button)
        
        self.register_button = QPushButton("注册")
        self.register_button.clicked.connect(self.handle_register)
        button_layout.addWidget(self.register_button)
        
        layout.addLayout(button_layout)
        
        # 状态标签
        self.status_label = QLabel("")
        self.status_label.setAlignment(Qt.AlignCenter)
        self.status_label.setStyleSheet("color: #d32f2f;")
        layout.addWidget(self.status_label)
        
        self.setLayout(layout)
    
    def handle_login(self):
        username = self.username_edit.text().strip()
        password = self.password_edit.text().strip()
        
        if not username or not password:
            self.status_label.setText("用户名和密码不能为空")
            return
        
        # 发送登录请求
        import requests
        try:
            response = requests.post(
                'http://localhost:5000/api/login',
                json={'username': username, 'password': password}
            )
            
            result = response.json()
            
            if result.get('success'):
                user_id = result.get('user_id')
                username = result.get('username')
                self.login_success.emit(user_id, username)
            else:
                self.status_label.setText(result.get('message', '登录失败'))
        except Exception as e:
            self.status_label.setText(f"网络错误: {str(e)}")
    
    def handle_register(self):
        username = self.username_edit.text().strip()
        password = self.password_edit.text().strip()
        
        if not username or not password:
            self.status_label.setText("用户名和密码不能为空")
            return
        
        # 发送注册请求
        import requests
        try:
            response = requests.post(
                'http://localhost:5000/api/register',
                json={'username': username, 'password': password}
            )
            
            result = response.json()
            self.status_label.setText(result.get('message', '注册失败'))
        except Exception as e:
            self.status_label.setText(f"网络错误: {str(e)}")

# 聊天窗口
class ChatWindow(QMainWindow):
    def __init__(self, user_id, username):
        super().__init__()
        self.user_id = user_id
        self.username = username
        self.current_chat = 'public'  # 'public' or user_id
        self.private_chats = {}  # {receiver_id: {'username': '...', 'widget': QWidget, ...}}
        self.init_socketio()
        time.sleep(5)
        self.init_ui()
        self.init_shortcuts()
        
    
    def init_ui(self):
        self.setWindowTitle(f"烈火聊天室 - {self.username}")
        self.setMinimumSize(800, 600)
        
        # 主部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QHBoxLayout(central_widget)
        
        # 左侧聊天区域
        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        
        # 聊天标签页
        self.tab_widget = QTabWidget()
        
        # 公共聊天标签
        self.public_chat_widget = QWidget()
        public_chat_layout = QVBoxLayout(self.public_chat_widget)
        
        self.public_messages_list = QTextEdit()
        self.public_messages_list.setReadOnly(True)
        self.public_messages_list.setFrameShape(QFrame.NoFrame)
        public_chat_layout.addWidget(self.public_messages_list)
        
        # 消息输入区域
        public_input_layout = QHBoxLayout()
        
        self.public_message_input = QLineEdit()
        self.public_message_input.setPlaceholderText("输入消息并按Enter发送...")
        self.public_message_input.returnPressed.connect(self.send_public_message)
        public_input_layout.addWidget(self.public_message_input)
        
        self.send_public_button = QPushButton("发送")
        self.send_public_button.clicked.connect(self.send_public_message)
        public_input_layout.addWidget(self.send_public_button)
        
        public_chat_layout.addLayout(public_input_layout)
        
        self.tab_widget.addTab(self.public_chat_widget, "公共聊天")
        
        left_layout.addWidget(self.tab_widget)
        main_layout.addWidget(left_widget, 3)
        
        # 分隔器
        splitter = QSplitter(Qt.Horizontal)
        main_layout.addWidget(splitter)
        
        # 右侧在线用户列表
        right_widget = QWidget()
        right_layout = QVBoxLayout(right_widget)
        
        online_label = QLabel("在线用户")
        online_label.setObjectName("onlineUserLabel")
        right_layout.addWidget(online_label)
        
        self.users_list_widget = QListWidget()
        self.users_list_widget.doubleClicked.connect(self.start_private_chat)
        right_layout.addWidget(self.users_list_widget)
        
        main_layout.addWidget(right_widget, 1)
        
        # 设置样式
        self.setStyleSheet(RED_THEME_STYLESHEET)
    
    def init_shortcuts(self):
        # Ctrl+P 切换到公共聊天
        self.public_chat_shortcut = QShortcut(QKeySequence("Ctrl+P"), self)
        self.public_chat_shortcut.activated.connect(self.switch_to_public_chat)
    
    def switch_to_public_chat(self):
        """切换到公共聊天标签页"""
        self.tab_widget.setCurrentWidget(self.public_chat_widget)
    
    def init_socketio(self):
        # 创建并启动WebSocket客户端线程
        self.socketio_thread = SocketIOClientThread(self.user_id, self.username)
        
        # 连接信号槽
        self.socketio_thread.user_online.connect(self.add_online_user)
        self.socketio_thread.user_offline.connect(self.remove_online_user)
        self.socketio_thread.online_users.connect(self.update_online_users)
        self.socketio_thread.public_message_received.connect(self.add_public_message)
        self.socketio_thread.private_message_received.connect(self.add_private_message)
        self.socketio_thread.connection_error.connect(self.show_connection_error)
        
        self.socketio_thread.start()
    
    def add_online_user(self, user_data):
        user_id = user_data.get('user_id')
        username = user_data.get('username')
        
        # 不显示自己
        if user_id == self.user_id:
            return
            
        # 检查用户是否已在列表中
        for i in range(self.users_list_widget.count()):
            item = self.users_list_widget.item(i)
            if item.data(Qt.UserRole) == user_id:
                return
        
        # 添加用户到列表
        item = QListWidgetItem(username)
        item.setData(Qt.UserRole, user_id)
        self.users_list_widget.addItem(item)
    
    def remove_online_user(self, user_data):
        user_id = user_data.get('user_id')
        # 从列表中移除用户
        for i in range(self.users_list_widget.count()):
            item = self.users_list_widget.item(i)
            if item.data(Qt.UserRole) == user_id:
                self.users_list_widget.takeItem(i)
                # 关闭对应的私聊标签页
                self.close_private_chat_tab(user_id)
                break
    
    def update_online_users(self, users_data):
        self.users_list_widget.clear()
        
        for user_data in users_data:
            user_id = user_data.get('user_id')
            username = user_data.get('username')
            
            # 不显示自己
            if user_id == self.user_id:
                continue
                
            item = QListWidgetItem(username)
            item.setData(Qt.UserRole, user_id)
            self.users_list_widget.addItem(item)
    
    def add_public_message(self, message_data):
        sender_id = message_data.get('sender_id')
        sender_username = message_data.get('sender_username')
        content = message_data.get('content')
        timestamp = message_data.get('timestamp')
        
        # 格式化时间
        try:
            dt = datetime.fromisoformat(timestamp)
            time_str = dt.strftime("%H:%M:%S")
        except:
            time_str = "未知时间"
        
        # 添加到消息列表
        self.public_messages_list.append(f"<b>{sender_username}</b> [{time_str}]:<br>{content}<br>")
        # 滚动到底部 - 修复QTextCursor.End错误
        cursor = self.public_messages_list.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.public_messages_list.setTextCursor(cursor)
    
    def add_private_message(self, message_data):
        sender_id = message_data.get('sender_id')
        sender_username = message_data.get('sender_username')
        content = message_data.get('content')
        timestamp = message_data.get('timestamp')
        
        # 格式化时间
        try:
            dt = datetime.fromisoformat(timestamp)
            time_str = dt.strftime("%H:%M:%S")
        except:
            time_str = "未知时间"
        
        # 检查是否已有该用户的私聊标签页
        tab_index = self.find_private_chat_tab(sender_id)
        
        if tab_index == -1:
            # 创建新的私聊标签页
            tab_index = self.create_private_chat_tab(sender_id, sender_username)
        
        # 切换到该标签页
        self.tab_widget.setCurrentIndex(tab_index)
        
        # 获取该标签页的消息列表部件
        private_chat_widget = self.tab_widget.widget(tab_index)
        messages_list = private_chat_widget.findChild(QTextEdit)
        
        if messages_list:
            messages_list.append(f"<b>{sender_username}</b> [{time_str}]:<br>{content}<br>")
            # 滚动到底部 - 修复QTextCursor.End错误
            cursor = messages_list.textCursor()
            cursor.movePosition(QTextCursor.End)
            messages_list.setTextCursor(cursor)
    
    def send_public_message(self):
        content = self.public_message_input.text().strip()
        
        if content:
            self.socketio_thread.send_public_message(content)
            self.public_message_input.clear()
    
    def start_private_chat(self):
        selected_items = self.users_list_widget.selectedItems()
        
        if not selected_items:
            return
            
        item = selected_items[0]
        user_id = item.data(Qt.UserRole)
        username = item.text()
        
        # 检查是否已有该用户的私聊标签页
        tab_index = self.find_private_chat_tab(user_id)
        
        if tab_index == -1:
            # 创建新的私聊标签页
            tab_index = self.create_private_chat_tab(user_id, username)
        
        # 切换到该标签页
        self.tab_widget.setCurrentIndex(tab_index)
    
    def create_private_chat_tab(self, user_id, username):
        # 创建私聊窗口部件
        private_chat_widget = QWidget()
        private_chat_layout = QVBoxLayout(private_chat_widget)
        
        # 消息列表
        messages_list = QTextEdit()
        messages_list.setReadOnly(True)
        messages_list.setFrameShape(QFrame.NoFrame)
        private_chat_layout.addWidget(messages_list)
        
        # 存储用户ID以便后续使用
        messages_list.setProperty("receiver_id", user_id)
        
        # 消息输入区域
        input_layout = QHBoxLayout()
        
        message_input = QLineEdit()
        message_input.setPlaceholderText(f"对 {username} 说...")
        message_input.returnPressed.connect(
            lambda receiver_id=user_id, input_widget=message_input: 
            self.send_private_message(receiver_id, input_widget)
        )
        input_layout.addWidget(message_input)
        
        send_button = QPushButton("发送")
        send_button.clicked.connect(
            lambda receiver_id=user_id, input_widget=message_input: 
            self.send_private_message(receiver_id, input_widget)
        )
        input_layout.addWidget(send_button)
        
        private_chat_layout.addLayout(input_layout)
        
        # 添加到标签页
        tab_index = self.tab_widget.addTab(private_chat_widget, f"与 {username} 聊天")
        
        # 存储私聊信息
        self.private_chats[user_id] = {
            'username': username,
            'widget': private_chat_widget,
            'messages_list': messages_list,
            'message_input': message_input
        }
        
        return tab_index
    
    def find_private_chat_tab(self, user_id):
        for i in range(self.tab_widget.count()):
            tab_widget = self.tab_widget.widget(i)
            if not tab_widget:
                continue
                
            messages_list = tab_widget.findChild(QTextEdit)
            if messages_list and messages_list.property("receiver_id") == user_id:
                return i
                
        return -1
    
    def close_private_chat_tab(self, user_id):
        if user_id in self.private_chats:
            # 找到标签页索引
            tab_index = self.find_private_chat_tab(user_id)
            if tab_index != -1:
                # 移除标签页
                self.tab_widget.removeTab(tab_index)
            
            # 从字典中删除
            del self.private_chats[user_id]
    
    def send_private_message(self, receiver_id, input_widget):
        content = input_widget.text().strip()
        
        if content and receiver_id in self.private_chats:
            # 发送消息
            self.socketio_thread.send_private_message(receiver_id, content)
            
            # 在本地显示自己发送的消息
            username = self.private_chats[receiver_id]['username']
            messages_list = self.private_chats[receiver_id]['messages_list']
            
            time_str = datetime.now().strftime("%H:%M:%S")
            messages_list.append(f"<b>我</b> [{time_str}]:<br>{content}<br>")
            
            # 滚动到底部 - 修复QTextCursor.End错误
            cursor = messages_list.textCursor()
            cursor.movePosition(QTextCursor.End)
            messages_list.setTextCursor(cursor)
            
            # 清空输入框
            input_widget.clear()
    
    def show_connection_error(self, error_msg):
        QMessageBox.critical(self, "连接错误", error_msg)

# 主应用
class ChatApplication(QApplication):
    def __init__(self, argv):
        super().__init__(argv)
        
        # 先显示登录窗口
        self.login_window = LoginWindow()
        self.login_window.login_success.connect(self.open_chat_window)
        self.login_window.show()
    
    def open_chat_window(self, user_id, username):
        # 关闭登录窗口
        self.login_window.close()
        # 打开聊天窗口
        self.chat_window = ChatWindow(user_id, username)
        self.chat_window.show()
        self.chat_window.remove_online_user({'user_id': user_id, 'username': username})

if __name__ == "__main__":
    app = ChatApplication(sys.argv)
    sys.exit(app.exec())